package com.learning.spring.cloud.ms.consumer.movie.feign;

import com.learning.spring.cloud.ms.consumer.movie.entity.User;
import feign.hystrix.FallbackFactory;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

/**
 * ClassName: UserFeignService
 * Description: Feign 客户端实现声明式REST调用,集成 hystrix 熔断
 * <p>
 * 1- 使用 @FeignClient 的 fallback 属性指定客户端添加回退类
 * 2- 使用 属性 fallbackFactory，了解回退的原因（如异常）
 * <p>
 * Date: 2019/6/4 14:59 【需求编号】
 *
 * @author Sam Sho
 * @version V1.0.0
 */
//@FeignClient(name = "ms-provider-user", fallback = UserFeignService.UserFeignServiceImplFallback.class)
@FeignClient(name = "ms-provider-user", fallbackFactory = UserFeignService.UserFeignServiceImplFallbackFactory.class)
public interface UserFeignService {

    /**
     * @param id
     * @return
     */
    @RequestMapping(value = "/user/{id}", method = RequestMethod.GET)
    User findById(@PathVariable("id") Long id);


    /**
     * fallback 属性指定的回退类
     */
    @Component
    class UserFeignServiceImplFallback implements UserFeignService {
        @Override
        public User findById(Long id) {
            User user = new User();
            user.setId(-1L);
            user.setName("默认用户");
            return user;
        }
    }

    /**
     * fallbackFactory 属性指定回退类。实现了解回退的原因（如异常），可以根据不同的异常，返回不同的信息。
     */
    @Slf4j
    @Component
    class UserFeignServiceImplFallbackFactory implements FallbackFactory<UserFeignService> {

        @Override
        public UserFeignService create(Throwable throwable) {

            // 日志最好放在各个fallback方法中，而不要直接放在create方法中。
            // 否则在引用启动时，就会打印该日志。
            // 详见https://github.com/spring-cloud/spring-cloud-netflix/issues/1471
            // 这边暂时简单处理

            log.error("回退：", throwable);
            return new UserFeignServiceImplFallback();
        }
    }


}
